#!/usr/bin/env python
"""
 Description : Main LH-ABC GUI python script.
               you can run from source code by using
               >python lh-abc.py
               need Python, WxPython in order to run from source code.
"""
import __builtin__

import sys
import os
import time
import gettext
import getopt
import tempfile
import mmap

if not getattr(sys, 'frozen', None):
    import wxversion
    wxversion.ensureMinimal('2.9.0.1')
import wx

from traceback import format_exc
from threading import Thread


from BitTornado.__init__ import product_name, version_short
from BitTornado.bencode import bencode, bdecode

from LMG.Utility.utility import Utility
from LMG.Utility.constants import *

from LMG.GUI.menus import MenuBar
from LMG.GUI.lists import TransferList    
from LMG.GUI.taskbaricon import TaskBarIcon    
from LMG.GUI.statusbar import StatusBar
from LMG.GUI.toolbars import MainToolBar
from LMG.GUI.details import DetailPanel
from LMG.GUI.Base.guiupdate import SafeInvocation, Event
from LMG.GUI.Base.WidgetStack import WidgetStack
from LMG.GUI.log import LogPanel
from LMG.Tools.search import SearchPanel
from LMG.Tools.rssgui import RSSPanel
from LMG.Tools.cmdscheduler import CommandScheduler
from LMG.Tools.ipfilter import FilterManager
from LMG.Tools.templates import LabelManager
from LMG.Tools.webservice import WEBSERVICE, WebService
from LMG.launchmanycore import LaunchMany
from LMG.Scheduler.scheduler import Scheduler

if (sys.platform[:3] == 'win'):
    from LMG.Utility.regchecker import RegCheckDialog

##############################################################
class MainPanel(wx.Panel):
    """
    Main Panel class contains the management notebook
    """
    def __init__(self, parent):
        """
        Initialize the main panel
        """
        self.postponedevents = []

        wx.Panel.__init__(self, parent, wx.ID_ANY, style = wx.CLIP_CHILDREN, name = "MainPanel")
        
        self.parent = parent
        utility.window = self
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        
        # Page Manager
        self.pages = {}
        self.pageManager = WidgetStack(self)
        
        # Splitter
        self.splitter = wx.SplitterWindow(self.pageManager, -1, style = wx.SP_LIVE_UPDATE)
        self.splitter.SetSashGravity(0.5)
        self.list = TransferList(self.splitter)
        self.details = DetailPanel(self.splitter)
        self.splitter.Bind(wx.EVT_SPLITTER_DCLICK, self.OnCloseSplitterWindow)

        # Details Pane
        style = wx.FRAME_TOOL_WINDOW|wx.RESIZE_BORDER|wx.SYSTEM_MENU|wx.CAPTION|wx.CLOSE_BOX|wx.CLIP_CHILDREN|wx.FRAME_FLOAT_ON_PARENT 
        self.detailsFrame =  wx.Frame(self.parent, -1, _('Torrent Inspector'), size = (650, 350), style = style)
        self.detailsFrame.SetTransparent(240)
        self.detailsFrame.Bind(wx.EVT_CLOSE, self.OnCloseDetailsWindow)
        try:
            self.detailsFrame.SetIcon(utility.icon)
        except:
            pass
        utility.actions[ACTION_TORRENTDETAILS].action(show = True)
        if not utility.config.Read('show_inspector', "boolean"):
            utility.actions[ACTION_TORRENTDETAILS].action(show = False)
        if utility.config.Read('framed_inspector', "boolean"):
            utility.actions[ACTION_TORRENTDETAILS].changeParent()
        
        # Add Pages
        self.pages['transfer'] = self.splitter
        self.pages['rss'] = RSSPanel(self.pageManager)
        self.pages['log'] = LogPanel(self.pageManager)
        self.pages['search'] = SearchPanel(self.pageManager)

        self.pageManager.AddWidget(self.pages['transfer'])
        self.pageManager.AddWidget(self.pages['rss'])
        self.pageManager.AddWidget(self.pages['search'])
        self.pageManager.AddWidget(self.pages['log'])
                
        sizer.Add(self.pageManager, 1, wx.EXPAND)
        self.SetSizer(sizer)

    def __getitem__(self, key):
        return self.pages[key]

    def __setitem__(self, key, page):
        self.pageManager.AddWidget(page)
        self.pages[key] = page
        if wx.Platform == "__WXMSW__":
            utility.actions[ACTION_THEME].setBackground(page)
        
    def __delitem__(self, key):
        self.pageManager.RemoveWidget(self.pages[key])
        del self.pages[key]
        
    def createPage(self, name, widget, *args, **kwargs):
        win = widget(self.pageManager, *args, **kwargs)
        self[name] = win
        
    def selectPage(self, page):
        if type(page) in (str, unicode):
            page = self.pages[page]
        self.pageManager.RaiseWidget(page)
        page.SetFocus()
        
    def getPages(self):
        return self.pages.values()

    def exists(self, name):
        return name in self.pages.keys()
    
    def OnCloseDetailsWindow(self, event):
        """ Hide details frame """
        if event.CanVeto():
            utility.actions[ACTION_TORRENTDETAILS].action()
            event.Veto()
            
    def OnCloseSplitterWindow(self, event):
        """ Show details frame"""
        utility.actions[ACTION_TORRENTDETAILS].changeParent()
        
##############################################################
                
class MainFrame(wx.Frame, SafeInvocation):
    """
    Main Frame class that contains MainPanel, menubar, statusbar, toolbar
    """
    def __init__(self, ID, params):
        """
        Initialize the main frame
        """
        utility.frame = self
        self.doneflag = Event()

        title = product_name + " " + version_short
        size, position = self._getWindowSettings()
        wx.Frame.__init__(self, None, ID, title, position, size, name = "MainFrame")
        SafeInvocation.__init__(self)

        #if wx.Platform == "__WXMSW__":
        #    if wx.GetApp().GetComCtl32Version() >= 600 and wx.DisplayDepth() >= 32:
        #        wx.SystemOptions.SetOptionInt("msw.remap", 2)
        #if wx.Platform == "__WXMAC__":
            #wx.SystemOptions.SetOptionInt("mac.listctrl.always_use_generic", 1)
            #self.SetExtraStyle(wx.FRAME_EX_METAL)

        # Don't update GUI as often when iconized
        self.GUIupdate = True

        # Set Application icon
        try:
            self.SetIcon(utility.icon)
        except:
            pass
        
        #######################################################
        # Main GUI stuff
        #######################################################

        # Scheduler
        ##############
        utility.queue  = Scheduler()
        
        # StatusBar
        ##############
        self.SetStatusBar(StatusBar(self))

        # MenuBar
        ##############
        self.SetMenuBar(MenuBar(self))

        # TaskBar icon
        ##############
        try:
            self.tbicon = TaskBarIcon(self)
        except:
            self.tbicon = None

        # Main Panel 
        ##############
        self.window = MainPanel(self)

        # Pref. Frame
        ##############
        self.preferences = None

        # ToolBar
        ##############
        self.tb = MainToolBar(self)
        self.SetToolBar(self.tb)
        
        # Command Scheduler
        ##############
        self.commandScheduler = CommandScheduler()

        # Win Settings  
        ##############
        self._loadWindowSettings()

        # Update Menu
        ##############
        self.updateMenuChecks()

        wx.LogMessage('GUI loaded')
        
        # Hot Key
        ############## 
        if wx.Platform == "__WXMSW__":
            self.openwin = []
            self.modaldlg = {}
            utility.hotkey = {"ID": wx.NewId(),
                              "modifiers": utility.config.Read('hotkeymod', "int"),
                              "keys": utility.config.Read('hotkeykeycode', "int"),
                              "wxkeycode": utility.config.Read('hotkeywxkeycode', "int"),
                              "current": {"modifiers": None,
                                          "keys": None,
                                          "wxkeycode": None},
                              "active": False,
                              "hiding": False}
            
            if utility.config.Read('hotkey', "boolean"):
                utility.hotkey["current"]["modifiers"] = utility.hotkey["modifiers"]
                utility.hotkey["current"]["keys"] = utility.hotkey["keys"]
                utility.hotkey["current"]["wxkeycode"] = utility.hotkey["wxkeycode"]     
                self.RegisterHotKey(utility.hotkey["ID"], utility.hotkey["modifiers"], utility.hotkey["keys"])
                utility.hotkey["active"] = True

        #######################################################
        # Events Table
        #######################################################
        self.Bind(wx.EVT_QUERY_END_SESSION, self.OnCloseWindow)
        self.Bind(wx.EVT_END_SESSION, self.OnCloseWindow)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(wx.EVT_ICONIZE, self.onIconify)
        self.Bind(wx.EVT_SIZE, self.onSize)
        self.Bind(wx.EVT_SHOW, self.onShow)
        if wx.Platform == "__WXMSW__":
            self.Bind(wx.EVT_HOTKEY, self.HotKeyDown, id = utility.hotkey["ID"])
            self.Bind(wx.EVT_SYS_COLOUR_CHANGED, self.OnSysColourChange)
        if wx.Platform == "__WXMAC__":
            self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
        
        # Accelerator Table
        fsID = wx.NewId()
        self.Bind(wx.EVT_MENU, self.onFullScreen, id = fsID)
        accelTable = wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_F11, fsID)])
        self.SetAcceleratorTable(accelTable)

        #######################################################
        # Set Up Filter Manager
        #######################################################
        utility.ipfilter = FilterManager()
        if utility.ipfilter:
            wx.LogMessage('Filter Manager: %d IP ranges loaded' % len(utility.ipfilter))
        #######################################################
        # Start the controller
        #######################################################
        utility.controller = LaunchMany()
        utility.controller.start()
        utility.queue.postInitTasks()
        wx.LogMessage('Controller loaded and started')

        #######################################################
        # Start DHT
        #######################################################
        if utility.dht:
            utility.dht.start()
            wx.LogMessage('DHT loaded')
            
        #######################################################
        # Set Up Label Manager
        #######################################################
        utility.labelmanager = LabelManager()
        
        #######################################################
        # Web Service
        #######################################################
        if WEBSERVICE:
            WebService()
        else:
            wx.LogMessage(_("Web Service disabled: Please download wsgiref or update to Python 2.5")) 

        #######################################################
        # Startup params
        #######################################################
        for param in params:
            wx.GetApp().MacOpenFile(param)  # Yes, even if the platform isn't Mac

        #######################################################
        # Check For Update
        #######################################################
        if utility.config.Read('checkforupdates', "boolean"):
            utility.actions[ACTION_UPDATECHECK].action()
            
        self.Show(True)
        
        # Check to see if ABC is associated with torrents
        #######################################################
        if (sys.platform[:3] == 'win') and \
           utility.config.Read('associate', "boolean") and \
           not utility.regchecker.testRegistry():
            dialog = RegCheckDialog(self)
            dialog.ShowModal()
            dialog.Destroy()
        
    #######################################
    # minimize to tray bar control
    #######################################
    def OnActivate(self, event):
        if event.GetActive():
            self.StatusBar.clean()
            self.setGUIupdate(True)
        event.Skip()
        
    def taskbarCallback(self):
        self.invokeLater(self.onTaskBarActivate, [])

    def onTaskBarActivate(self, event = None, close = False):
        # In case frame is already shown, hide it.
        if self.IsShown() and event is not None:
            self.Iconize(True)
            return
        
        self.Iconize(False)
        self.Show(True)
        self.Raise()

        if close and self.IsMaximized():
            self.Iconize(False)
            
        if self.tbicon is not None:
            self.tbicon.updateIcon(close = close)

        # Resume updating GUI
        self.setGUIupdate(True)

    def onIconify(self, event = None):
        """
        This event handler is called both when being
        minimalized and when being restored.
        """
        if event is None:
            self.Iconize(True)
            if self.tbicon is not None:
                self.tbicon.updateIcon(True)
                self.Show(False)
            self.setGUIupdate(False)
        elif event.Iconized():
            if self.tbicon is not None \
               and 0 < utility.config.Read('mintray', "int") != 2:
                self.tbicon.updateIcon(True)
                self.Show(False)                    
            self.setGUIupdate(False)
        else:
            self.setGUIupdate(True)
        if event is not None:
            event.Skip()

    #######################################
    # Setting GUI Update
    #######################################
    def onSize(self, event = None):
        self.setGUIupdate(True)
        if event is not None:
            event.Skip()
            
    def onShow(self, event):
        self.setGUIupdate(event.GetShow())
        event.Skip()
        
    def setGUIupdate(self, update):
        if update == self.GUIupdate:
            return
        
        self.GUIupdate = update
        if self.GUIupdate:
            # Force an update of all torrents
            for torrent in utility.torrents["all"]:
                torrent.updateColumns()
            utility.window.details.updateAll()
        #else:
        #    print "NOT?"
        #    # Clear selection [no details]
        #    #utility.window.list.unSelectAll()        

    #######################################
    # Window Settings
    #######################################
    def onFullScreen(self, event = None):
        """
        Toggles full screen mode 
        """
        if self.IsFullScreen():
            self.ShowFullScreen(False)
        elif event:
            # keep toolbar and menubar... for now
            #wx.FULLSCREEN_NOMENUBAR | wx.FULLSCREEN_NOTOOLBAR 
            style = wx.FULLSCREEN_NOSTATUSBAR | wx.FULLSCREEN_NOCAPTION |wx.FULLSCREEN_NOBORDER
            self.ShowFullScreen(True, style)

        if event:
            event.Skip()

    def updateMenuChecks(self):
        for action in utility.actions.values():
            if hasattr(action, "updateCheck"):
                action.updateCheck()

        # page selector
        utility.actions[ACTION_PAGE_SELECTION].updateButton()
        # Directory Scanner
        utility.actions[ACTION_DIRSCANNER].updateButton()
        
    def _getWindowSettings(self):
        width = utility.config.Read("window_width")
        height = utility.config.Read("window_height")
        try:
            size = wx.Size(int(width), int(height))
        except:
            size = wx.Size(710, 400)
        
        x = utility.config.Read("window_x")
        y = utility.config.Read("window_y")
        if (x == "" or y == ""):
            position = wx.DefaultPosition
        else:
            position = wx.Point(int(x), int(y))

        return size, position
        
    def _saveWindowSettings(self):
        width, height = self.GetSizeTuple()
        x, y = self.GetPositionTuple()
        utility.config.Write("window_x", x)
        utility.config.Write("window_y", y)
        utility.config.Write("window_width", width)
        utility.config.Write("window_height", height)

        utility.config.Write("show_statusbar", self.StatusBar.IsShown(), "boolean")
        utility.config.Write("show_toolbar", self.tb.IsShown(), "boolean")
        utility.config.Write("show_inspector", utility.window.details.IsShown() and not utility.actions[ACTION_TORRENTDETAILS].isFramed(), "boolean")
        utility.config.Write("framed_inspector", utility.actions[ACTION_TORRENTDETAILS].isFramed(), "boolean")

        if utility.window.splitter.IsSplit():
            utility.config.Write("splitter_pos", utility.window.splitter.GetSashPosition(), "int")

        utility.config.Flush()

    def OnSysColourChange(self, event):
        try:
            utility.actions[ACTION_THEME].update()
        except:
            pass
        event.Skip()
        
    def _loadWindowSettings(self):
        # Hide statusbar if needed
        if not utility.config.Read("show_statusbar", "boolean"):
            utility.actions[ACTION_VIEWSTATUSBAR].action()
        # Hide toolbar if needed
        if not utility.config.Read("show_toolbar", "boolean"):
            utility.actions[ACTION_VIEWTOOLBAR].action()
        # Make sure the current position is valid
        self.RepositionInScreen()
        # Maximize if needed
        if utility.config.Read('maximized', "boolean"):
            self.Maximize()
        # Mac fix
        if wx.Platform == "__WXMAC__":
            self.SetSize(self._getWindowSettings()[0])
        # Apply theme color
        if wx.Platform == "__WXMSW__":
            utility.actions[ACTION_THEME].update()
	
    def RepositionInScreen(self):
        displayRect = wx.GetClientDisplayRect()
        currentRect = self.GetRect()
        if currentRect.IsEmpty() or displayRect.IsEmpty():
            return False
        if currentRect.top < displayRect.top:
            currentRect.y += displayRect.top - currentRect.top
        if currentRect.bottom > displayRect.bottom:
            currentRect.y += displayRect.bottom - currentRect.bottom
        if currentRect.left < displayRect.left:
            currentRect.x += displayRect.left - currentRect.left
        if currentRect.right > displayRect.right:
            currentRect.x += displayRect.right - currentRect.right
        self.SetRect(currentRect)
        return True    

    def _Refresh(self):
        self.Layout()
        self.SendSizeEvent()
        self.Refresh()

    ##################################
    # Hot Key Control
    ##################################      
    def HotKeyDown(self, event=None):
        """
        Hides/Shows the entire application
        """
        if utility.hotkey["hiding"]:
            for item in self.openwin:
                item.Show()
            for item in self.modaldlg:
                item.SetPosition(self.modaldlg[item])
                item.SetFocus()
                
            if self.IsIconized():
                self.tbicon.updateIcon(True)
            else:
                self.tbicon.updateIcon()
                # Resume updating GUI
                self.setGUIupdate(True)
        else:
            self.openwin = []
            self.modaldlg = {}
            for item in wx.GetTopLevelWindows():
                if hasattr(item, "GetFrame"):
                    item = item.GetFrame()
                if item.IsShown():
                    if (not hasattr(item, "IsModal")) or not item.IsModal():
                        item.Hide()
                        self.openwin.append(item)
                    else:
                        self.modaldlg[item] = item.GetPosition()
                        item.SetPosition(wx.Point(-0xFFFF, -0xFFFF))
            if self.tbicon.IsIconInstalled():
                self.tbicon.RemoveIcon()
            # stop updating GUI
            self.setGUIupdate(False)

        utility.hotkey["hiding"] = not utility.hotkey["hiding"]

    ##################################
    # Close Program
    ##################################
    def OnClose(self, event):
        # FIXME: Mac Hack for now...
        if wx.Platform == "__WXMAC__":
            if hasattr(wx.GetApp(), "MacHideApp"):
                wx.GetApp().MacHideApp()
            else:
                self.OnCloseWindow(event)
            return
        
        # Mimimize on close
        if utility.config.Read("mintray", "int") == 2 and event.CanVeto():
            self.onIconify()
            event.Veto()
        # Destroy on close
        else:
            self.OnCloseWindow(event)
                                    
    def OnCloseWindow(self, event = None, silent = False, shutdown = False):
        if utility.quitting:
            return
        
        if not silent and utility.config.Read('confirmonclose', "boolean") \
           and (event is None or event.CanVeto()):
            dialog = wx.MessageDialog(None,
                                      _('Are you sure you want to exit?'),
                                      _('Exit Confirmation'),
                                      wx.OK|wx.CANCEL)
            result = dialog.ShowModal()
            dialog.Destroy()
            if result != wx.ID_OK:
                if event: event.Veto()
                return

        utility.quitting = True

        # tell scheduler to close all active thread
        utility.queue.clearScheduler()

        # Cancel logger
        try:
            utility.window['log'].install(False)
        except:
            pass
        
        # Make sure not hidden
        if wx.Platform == "__WXMSW__" and utility.hotkey["hiding"]: 
            self.HotKeyDown()

        # Close Torrent Maker
        utility.actions[ACTION_MAKER].closeWin()

        # Stop Web Service
        try:
            utility.webserver.stop()
        except:
            pass
        
        # Stop Web Service
        try:
            self.commandScheduler.stop()
        except:
            pass

        # Save Window Size/Perspective
        self.onFullScreen()
        utility.config.Write('maximized', self.IsMaximized(), "boolean")
        self.onTaskBarActivate(close = True)
        self._saveWindowSettings()

        # Shutdown computer
        if shutdown:
            self.ShutDown()

        # Destroy Icon
        if self.tbicon is not None:
            self.tbicon.Destroy()
            self.tbicon = None
            
        # Destroy
        self.Destroy()
        
    def ShutDown(self):
        # Disable hotkey function
        if wx.Platform == "__WXMSW__" and utility.hotkey["active"]:
            if not self.UnregisterHotKey(utility.hotkey["ID"]):
                self.Bind(wx.EVT_HOTKEY, None)

        # Wait 3 minutes before shutting down
        self.Hide()
        delacdlg = wx.ProgressDialog(_('Shutting Down Computer'), _('A computer shutdown will occur soon'),
                                        maximum = 720, style = wx.PD_CAN_ABORT | wx.PD_AUTO_HIDE)
        keepgoing = True
        count = 0
        while keepgoing and count < 720:
            count += 1
            wx.MilliSleep(250)
            keepgoing = delacdlg.Update(count)
            if type(keepgoing) is tuple:
                keepgoing = keepgoing[0]
        delacdlg.Destroy()
        if keepgoing:
            utility.shutdownComputer()
                
##############################################################
class MainApp(wx.App):
    """
    Main application class that contains MainFrame Object
    """
    def __init__(self, x, params, path):
        """
        Initialize application
        """
        self.params = params
        self.path = path
        self.local = False
        wx.App.__init__(self, x)

    def OnInit(self):
        """
        Called on Initialization
        Sets Utility which will be used for communications between all objects
        """
        # Redirect output to avoid py2exe logging of IPC "error"
        stderr = sys.stderr
        sys.stderr = sys.__stderr__

        # Get Parameters
        try:
            opts, args = getopt.getopt(self.params, "l", ["local"])
        except getopt.GetoptError, err:
            print str(err)
            return False
        self.local = ("-l", "") in opts or ("--local", "") in opts
        self.params = args

        # Create single instance semaphore (from pydocview in wx.lib)
        if wx.Platform == '__WXMSW__':
            tfile = tempfile.TemporaryFile(prefix="lh", suffix="tmp")
            fno = tfile.fileno()
            self._sharedMemory = mmap.mmap(fno, 1024, "shared_memory")
        else:
            tfile = file(os.path.join(tempfile.gettempdir(), tempfile.gettempprefix() + self.GetAppName() + '-' + wx.GetUserId() + "LHSharedMemory"), 'w+b')
            tfile.write("*")
            tfile.seek(1024)
            tfile.write(" ")
            tfile.flush()
            fno = tfile.fileno()
            self._sharedMemory = mmap.mmap(fno, 1024)

        self.single_instance_checker = wx.SingleInstanceChecker(product_name + '-' + wx.GetUserId(), tempfile.gettempdir())
        if self.single_instance_checker.IsAnotherRunning():
            data = bencode(self.params)
            while True:
                self._sharedMemory.seek(0)
                marker = self._sharedMemory.read_byte()
                if marker == '\0' or marker == '*':
                    self._sharedMemory.seek(0)
                    self._sharedMemory.write_byte('-')
                    self._sharedMemory.write(data)
                    self._sharedMemory.seek(0)
                    self._sharedMemory.write_byte('+')
                    self._sharedMemory.flush()
                    break
                else:
                    time.sleep(1)
            return False     
        else:
            self._timer = wx.PyTimer(self.DoBackgroundListenAndLoad)
            self._timer.Start(250)
        sys.stderr = stderr

        # Disable automatic updateUIEvents
        wx.UpdateUIEvent.SetUpdateInterval(-1)

        # set Utility
        __builtin__.utility = Utility(self.path)
                              
        # standard gettext support
        localedir = os.path.join(utility.getSharePath(), "locale")
        self.langid = utility.config.Read('lang', "int")
        domain = "messages"

        # Set locale for wxWidgets
        self.locale = wx.Locale(self.langid)
        self.locale.AddCatalogLookupPathPrefix(localedir)
        self.locale.AddCatalog(domain)
        
        # Set up Python's gettext
        self.translation = gettext.translation(domain, localedir,
            [self.locale.GetCanonicalName()], fallback = True)
        self.translation.install(unicode=True)        

        # RTL support?
        #del self.locale
        
        # Post app initialization
        utility.postAppInit()
        
        # set the Main Frame
        try:
            self.frame = MainFrame(wx.ID_ANY, self.params)            
        except:
            utility.frame.Destroy()
            dlg = wx.MessageDialog(None, _("Could not start") + ' ' + product_name + '\n' + \
                                        format_exc(), _('Error!'), wx.OK|wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return False
            
        self.SetTopWindow(self.frame)
        
        # Event Table
        self.Bind(wx.EVT_QUERY_END_SESSION, self.frame.OnCloseWindow)
        self.Bind(wx.EVT_END_SESSION, self.frame.OnCloseWindow)

        return True
    
    def MacOpenFile(self, filename):
        """
        Catch mac's drag&drop option
        """
        if os.path.isdir(filename):
            utility.queue.addtorrents.ScanTorrentDir(filename)
        else:
            utility.queue.addtorrents.AddTorrentFromFile(filename)
            
    def OnExit(self):
        """
        Close the application
        """
        del self.single_instance_checker
        return 0
    
    def DoBackgroundListenAndLoad(self):
        """
        Open any files specified in the given command line argument passed in via shared memory
        """        
        self._timer.Stop()

        self._sharedMemory.seek(0)
        if self._sharedMemory.read_byte() == '+':
            data = self._sharedMemory.read(1024-1)
            self._sharedMemory.seek(0)
            self._sharedMemory.write_byte("*")
            self._sharedMemory.flush()
            args = bdecode(data, sloppy = True)
            if type(args) == list:
                for arg in args:
                    self.MacOpenFile(arg)
                utility.frame.taskbarCallback()

        self._timer.Start(1000) # 1 seconds interval

##############################################################
def run(params = None):
    """
    Main Program Start Here
    """
    if params is None:
        params = []
    
    if len(sys.argv) > 1:
        params = sys.argv[1:]
    path = os.path.abspath(os.path.dirname(sys.argv[0]))
    os.chdir(path)
    
    app = MainApp(0, params, path)
    app.MainLoop()

if __name__ == '__main__':
    run()

